package de.fhaugsburg.games.boardgames.scrabble.robot;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

import de.fhaugsburg.games.boardgames.GridPoint;
import de.fhaugsburg.games.boardgames.ManhattanDirection;
import de.fhaugsburg.games.boardgames.exceptions.GameException;
import de.fhaugsburg.games.boardgames.exceptions.IllegalMoveException;
import de.fhaugsburg.games.boardgames.scrabble.IScrabbleBot;
import de.fhaugsburg.games.boardgames.scrabble.IScrabbleEngine;
import de.fhaugsburg.games.boardgames.scrabble.WordManager;
import de.fhaugsburg.games.boardgames.scrabble.scrabbleboard.LetterPiece;
import de.fhaugsburg.games.boardgames.scrabble.scrabbleboard.ScrabbleBoard;
import de.fhaugsburg.games.boardgames.scrabble.wordlist.IWordList;

public class GreedyScrabbleBot implements IScrabbleBot{

	
	private IScrabbleEngine engine;
	private IWordList wordList;
	private final ScrabbleBoard board;
	private List<LetterPiece> myLetters;
	private WordManager wordManager;
	private Logger logger;
	
	/**
	 * constructor
	 * @param engine
	 */
	public GreedyScrabbleBot(final IScrabbleEngine engine, IWordList wordList){
		//load all available Words from WordList, interface should be used
//		wordList = new WordArrayList();
		//wordList = new WordTrieList();
		this.wordList = wordList;

		this.engine = engine;
		this.board = engine.getBoard();
		this.wordManager = engine.getWordManager();
		
		this.logger = Logger.getLogger(this.getClass().getName());
		logger.setLevel(Level.OFF);
		logger.setUseParentHandlers(false);
		ConsoleHandler ch = new ConsoleHandler();
		ch.setLevel(Level.ALL);
	    logger.addHandler(ch);
		
	}


	/**
	 * getMove is called from outside to get a valid move from the robot
	 * if no valid move is found, null is returned
	 * @throws IllegalMoveException 
	 */
	public void makeMove() throws IllegalMoveException {
		
		this.myLetters = engine.getActivePlayer().getMyPieces();

		
//		Iterator<GridPoint> it = board.iterator(letters.first(), direction.gridPoint, true);
		int boardWidth = board.getWidth();
		int boardHeight = board.getHeight();
		
		ManhattanDirection[] horzVert = {ManhattanDirection.RIGHT, ManhattanDirection.DOWN}; 

		
		for (int y = 0; y < boardHeight; y++) {
			for (int x = 0; x < boardWidth; x++) {
				for (ManhattanDirection direction : horzVert){
					if(greedyWords (direction, new GridPoint(x, y))){
						try {
							engine.commitMove();
							return;
						}catch(GameException e){
							logger.finer("commit failed at " + x +", " + y);
							engine.undoLastMove();
						}
					}
				}
			}
		}
		logger.fine("nothing found, given up. pass.");
		engine.undoLastMove();
		wordManager.reset();
		engine.exchangeAllPlayersPieces();
		engine.passMove();
	}
	
	
	
	/**
	 * try to place one word
	 * @param direction
	 * @param gridPoint
	 * @return
	 */
	private boolean greedyWords(ManhattanDirection direction, GridPoint gridPoint){
		engine.undoLastMove();
		wordManager.reset();
		Iterator<GridPoint> boardWalk = board.iterator(gridPoint, direction.gridPoint, true);
		
		try {
		//walk the board
		while (boardWalk.hasNext()){
			GridPoint currentPos = boardWalk.next();
			
			//clone letters
			List<LetterPiece> letterPool = new ArrayList<LetterPiece>(myLetters);  

			
			//empty square, place letter
			if (board.getPiece(currentPos) == null){
				for (LetterPiece letter : letterPool){
					engine.setLetter(letter, currentPos);
					//prefix not in our wordList?
					List<String> newWords = wordManager.getProducedWords();
					if (!wordList.containsPrefix(newWords)){
						engine.removeLetter(currentPos);
					}else{
						//continue to next position on board, valid prefix
						break;
					}
				}
			//already a letter on this square?
			}else{
				//just continue to next square
			}
			
			//all produced words in our wordlist?
			if(wordList.contains(wordManager.getProducedWords())){
				logger.finest("trying to commit words: (" + gridPoint.toString() + ") " + wordManager.getProducedWords());
				return true;
			}else{
			//	return false;
			}
		}
		}catch(Exception e){
			//something went wrong, unable to find word
			return false;
		}
		
		return false;
	}
	
	
	
	
	
	
}
